#include "RequestNotifier.h"
#include "MessagePoster.h"
#include <qbkernel/include/qb_base.h>

RequestNotifier& RequestNotifier::instance()
{
	static RequestNotifier s_rn;
	return s_rn;
}

void RequestNotifier::registReqReceiver(int req, MessageReceiver* pr)
{
	qb::base::ScopedLock<qb::base::Spinlock> locker(m_lock);
	m_receivers[req] = pr;
}

void RequestNotifier::unRegistReqReceiver(int req, MessageReceiver* pr)
{
	qb::base::ScopedLock<qb::base::Spinlock> locker(m_lock);
	auto iter = m_receivers.find(req);
	if (iter != m_receivers.end())
		m_receivers.erase(iter);
}

void RequestNotifier::registPushReceiver(const PushMsgInfo& pmi, MessageReceiver* pr)
{
	qb::base::ScopedLock<qb::base::Spinlock> locker(m_pushLock);
	m_pushReceivers[pmi] = pr;
	m_paramExtractors[pmi.funcId] = pmi.extractFuncPtr;
}

void RequestNotifier::unRegistPushReceiver(const PushMsgInfo& pmi, MessageReceiver* pr)
{
	qb::base::ScopedLock<qb::base::Spinlock> locker(m_pushLock);
	m_pushReceivers.erase(pmi);
}

void RequestNotifier::OnResponse(THIS_ int32_t funcId, const qb::SSAckMsg& msg)
{
	{
		qb::base::ScopedLock<qb::base::Spinlock> locker(m_pushLock);
		auto extractor = m_paramExtractors.find(funcId);
		if (extractor != m_paramExtractors.end() && extractor->second)
		{
			NotifyFunc func = std::bind(&RequestNotifier::notifyPushReceiver, this, std::placeholders::_1, std::placeholders::_2);
			extractor->second(msg, func);
		}
		else
		{
			auto iter = m_pushReceivers.find({funcId, "", nullptr});
			if (iter != m_pushReceivers.end())
				iter->second->onDataArrived(msg);
		}
			
	}

	{
		qb::base::ScopedLock<qb::base::Spinlock> locker(m_lock);
		int req = msg.m_RequestID;
		auto iter = m_receivers.find(req);
		if (iter != m_receivers.end())
			iter->second->onDataArrived(msg);
	}
	
}

void RequestNotifier::notifyPushReceiver(const PushMsgInfo& pmi, const qb::SSAckMsg& msg)
{
	auto iter = m_pushReceivers.find(pmi);
	if (iter != m_pushReceivers.end())
		iter->second->onDataArrived(msg);
}

bool PushMsgInfo::operator<(const PushMsgInfo& other) const
{
	if (funcId < other.funcId)
		return true;
	if (funcId == other.funcId)
		return paramter < other.paramter;

	return false;
}

bool PushMsgInfo::operator == (const PushMsgInfo& other) const
{
	if (funcId == other.funcId && paramter == other.paramter)
		return true;

	return false;
}


void registSpecificMsgProcessor()
{
	static bool s_done = false;
	if (s_done)
		return;

	qb::qbBase::getMessageBond()->SetSpecificMsgProcessor(&RequestNotifier::instance());
}

void unRegistSpecificMsgProcessor()
{
	qb::qbBase::getMessageBond()->SetSpecificMsgProcessor(nullptr);
}
